package io.cici.cc.mybatis.lite.sql_source.scripting.ognl;

import lombok.extern.slf4j.Slf4j;
import ognl.ClassResolver;
import ognl.MemberAccess;
import ognl.OgnlException;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public final class Ognl {

    private static final MemberAccess OGNL_MEMBER_ACCESS = new MemberAccessImpl();
    private static final ClassResolver OGNL_CLASS_RESOLVER = new ClassResolverImpl();
    private static final Map<String, Object> expressionToTreeMap = new ConcurrentHashMap<>();

    private Ognl() {
    }

    public static Object getValue(Object root, String expression) {
        Map context = ognl.Ognl.createDefaultContext(root, OGNL_MEMBER_ACCESS, OGNL_CLASS_RESOLVER, null);
        try {
            return ognl.Ognl.getValue(parseExpression(expression), context, root);
        } catch (OgnlException e) {
            log.error("ognl表达式获取值失败", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 相同表达式解析处理tree是一样的。
     */
    private static Object parseExpression(String expression) {
        Object node = expressionToTreeMap.get(expression);
        if (node == null) {
            try {
                node = ognl.Ognl.parseExpression(expression);
            } catch (OgnlException e) {
                log.error("ognl表达式解析失败", e);
                throw new RuntimeException(e);
            }
            expressionToTreeMap.put(expression, node);
        }
        return node;
    }

}
